package org.dromara.nursing.service.impl;

import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.mybatis.core.page.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.dromara.nursing.domain.bo.AdmissionContractBo;
import org.dromara.nursing.domain.vo.AdmissionContractVo;
import org.dromara.nursing.domain.AdmissionContract;
import org.dromara.nursing.domain.BedInfo;
import org.dromara.nursing.domain.RoomInfo;
import org.dromara.nursing.domain.ElderBasic;
import org.dromara.nursing.domain.FeeRecord;
import org.dromara.nursing.domain.ElderOutstandingFees;
import org.dromara.nursing.mapper.AdmissionContractMapper;
import org.dromara.nursing.mapper.BedInfoMapper;
import org.dromara.nursing.mapper.RoomInfoMapper;
import org.dromara.nursing.mapper.ElderBasicMapper;
import org.dromara.nursing.mapper.FeeRecordMapper;
import org.dromara.nursing.mapper.ElderOutstandingFeesMapper;
import org.dromara.nursing.service.IAdmissionContractService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.dromara.common.satoken.utils.LoginHelper;
import cn.dev33.satoken.stp.StpUtil;

import java.util.List;
import java.util.Map;
import java.util.Collection;

/**
 * 入住流程Service业务层处理
 *
 * @author Xue
 * @date 2025-04-08
 */
@RequiredArgsConstructor
@Service
public class AdmissionContractServiceImpl implements IAdmissionContractService {

    private static final Logger log = LoggerFactory.getLogger(AdmissionContractServiceImpl.class);

    private final AdmissionContractMapper baseMapper;
    private final BedInfoMapper bedInfoMapper;
    private final RoomInfoMapper roomInfoMapper;
    private final ElderBasicMapper elderBasicMapper;
    private final FeeRecordMapper feeRecordMapper;
    private final ElderOutstandingFeesMapper elderOutstandingFeesMapper;

    private static final String FAMILY_ROLE_KEY = "jiashu";
    private static final String ADMIN_ROLE_KEY = "admin_ms";
    private static final String SUPER_ADMIN_ROLE_KEY = "admin";

    /**
     * 查询入住流程
     *
     * @param contractId 主键
     * @return 入住流程
     */
    @Override
    public AdmissionContractVo queryById(Long contractId){
        return baseMapper.selectVoById(contractId);
    }

    /**
     * 分页查询入住流程列表
     *
     * @param bo        查询条件
     * @param pageQuery 分页参数
     * @return 入住流程分页列表
     */
    @Override
    public TableDataInfo<AdmissionContractVo> queryPageList(AdmissionContractBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<AdmissionContract> lqw = buildQueryWrapper(bo);
        Page<AdmissionContractVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }

    /**
     * 查询符合条件的入住流程列表
     *
     * @param bo 查询条件
     * @return 入住流程列表
     */
    @Override
    public List<AdmissionContractVo> queryList(AdmissionContractBo bo) {
        LambdaQueryWrapper<AdmissionContract> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<AdmissionContract> buildQueryWrapper(AdmissionContractBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<AdmissionContract> lqw = Wrappers.lambdaQuery();

        // 自定义排序逻辑：待审核(0)排在前面，然后是已审核(1)，最后是已退回(2)
        // 同时按照ID倒序排序，确保最新的记录排在前面
        lqw.last("ORDER BY CASE is_check_contract " +
                 "WHEN '0' THEN 0 " +  // 待审核排第一
                 "WHEN '1' THEN 1 " +  // 已审核排第二
                 "WHEN '2' THEN 2 " +  // 已退回排第三
                 "ELSE 3 END, contract_id DESC");

        // 添加查询条件
        lqw.like(StringUtils.isNotBlank(bo.getElderName()), AdmissionContract::getElderName, bo.getElderName());
        lqw.eq(StringUtils.isNotBlank(bo.getContractNo()), AdmissionContract::getContractNo, bo.getContractNo());
        lqw.eq(StringUtils.isNotBlank(bo.getIsCheckContract()), AdmissionContract::getIsCheckContract, bo.getIsCheckContract());

        // 基于角色的数据权限过滤
        boolean isFamilyUser = StpUtil.hasRole(FAMILY_ROLE_KEY);
        boolean isAdminUser = StpUtil.hasRole(ADMIN_ROLE_KEY) || StpUtil.hasRole(SUPER_ADMIN_ROLE_KEY);

        // 如果是家属用户，只能查看自己关联的入住申请
        if (isFamilyUser && !isAdminUser) {
            Long userId = LoginHelper.getUserId();
            if (userId != null) {
                log.info("家属用户 {} 查询关联的入住申请", userId);
                lqw.eq(AdmissionContract::getContactUserId, userId);
            }
        }

        return lqw;
    }

    /**
     * 新增入住流程
     *
     * @param bo 入住流程
     * @return 是否新增成功
     */
    @Override
    public Boolean insertByBo(AdmissionContractBo bo) {
        try {
            AdmissionContract add = MapstructUtils.convert(bo, AdmissionContract.class);
            validEntityBeforeSave(add);

            // 检查老人是否已经入住
            if (add.getElderId() != null) {
                ElderBasic elderBasic = elderBasicMapper.selectById(add.getElderId());
                if (elderBasic != null) {
                    // 设置身份证号
                    if (StringUtils.isNotEmpty(elderBasic.getIdCard())) {
                        add.setIdCard(elderBasic.getIdCard());
                    }

                    // 检查老人是否已经分配了房间
                    if (elderBasic.getRoomId() != null && StringUtils.isNotEmpty(elderBasic.getRoomNumber())) {
                        log.warn("老人[{}]已经入住，房间号为: {}", elderBasic.getElderName(), elderBasic.getRoomNumber());
                        throw new RuntimeException("老人已经入住，不能重复分配房间");
                    }
                }
            }

            // 判断当前用户角色
            boolean isFamilyUser = StpUtil.hasRole(FAMILY_ROLE_KEY);
            boolean isAdminUser = StpUtil.hasRole(ADMIN_ROLE_KEY) || StpUtil.hasRole(SUPER_ADMIN_ROLE_KEY);

            // 设置当前用户ID为联系人用户ID
            Long currentUserId = LoginHelper.getUserId();
            if (currentUserId != null) {
                add.setContactUserId(currentUserId);
                log.info("设置联系人用户ID: {}", currentUserId);
            }

            // 设置审核状态
            // 家属用户提交的申请默认为待审核状态
            // 管理员提交的申请可以直接设置为已审核状态
            if (isFamilyUser) {
                // 家属用户提交的申请一律设置为待审核
                add.setIsCheckContract("0");
                log.info("家属用户提交申请，设置为待审核状态");
            } else if (isAdminUser) {
                // 管理员可以直接设置审核状态，如果未指定则默认为待审核
                if (StringUtils.isEmpty(add.getIsCheckContract())) {
                    add.setIsCheckContract("0");
                }
                log.info("管理员提交申请，审核状态为: {}", add.getIsCheckContract());
            } else {
                // 其他用户提交的申请默认为待审核
                add.setIsCheckContract("0");
                log.info("其他用户提交申请，设置为待审核状态");
            }

            // 插入入住合同记录
            boolean flag = baseMapper.insert(add) > 0;
            if (flag) {
                bo.setContractId(add.getContractId());
                log.info("入住合同创建成功: contractId={}, elderName={}, roomNumber={}, bedNumber={}",
                    add.getContractId(), add.getElderName(), add.getRoomNumber(), add.getBedNumber());

                // 只有管理员提交且状态为已审核的申请才立即执行资源分配
                if (isAdminUser && "1".equals(add.getIsCheckContract())) {
                    try {
                        // 获取完整的合同数据
                        AdmissionContract freshContract = baseMapper.selectById(add.getContractId());
                        if (freshContract != null) {
                            log.info("管理员直接审核通过，开始分配资源: contractId={}", freshContract.getContractId());

                            // 执行资源分配
                            updateBedStatus(freshContract);
                            updateRoomAvailableBeds(freshContract.getRoomId());
                            updateElderRoomInfo(freshContract);

                            log.info("资源分配完成: contractId={}", freshContract.getContractId());
                        } else {
                            log.error("无法获取完整合同信息: contractId={}", add.getContractId());
                        }
                    } catch (Exception e) {
                        log.error("资源分配失败", e);
                        // 资源分配失败不影响合同创建结果
                    }
                } else {
                    log.info("入住合同待审核，暂不分配资源: contractId={}, isCheckContract={}",
                        add.getContractId(), add.getIsCheckContract());
                }
            }
            return flag;
        } catch (Exception e) {
            log.error("新增入住合同失败", e);
            return false;
        }
    }

    /**
     * 更新床位状态
     *
     * @param contract 入住合同
     */
    private void updateBedStatus(AdmissionContract contract) {
        try {
            if (contract.getRoomId() == null || StringUtils.isEmpty(contract.getBedNumber()) || contract.getElderId() == null) {
                log.warn("床位信息不完整或老人ID为空，无法更新床位状态: roomId={}, bedNo={}, elderId={}", contract.getRoomId(), contract.getBedNumber(), contract.getElderId());
                return;
            }

            // 首先查询找到对应的床位记录
            LambdaQueryWrapper<BedInfo> queryWrapper = Wrappers.lambdaQuery();
            queryWrapper.eq(BedInfo::getRoomId, contract.getRoomId());

            // 直接使用完整的床位号进行查询，不再提取纯床号
            // 这样可以确保与前端传递的床位号格式一致
            queryWrapper.eq(BedInfo::getBedNumber, contract.getBedNumber());

            // 记录日志
            log.info("查询床位信息: roomId={}, bedNumber={}", contract.getRoomId(), contract.getBedNumber());

            // 查询床位信息
            BedInfo bedInfo = bedInfoMapper.selectOne(queryWrapper);
            if (bedInfo != null) {
                log.info("找到床位记录: bedId={}, roomId={}, bedNumber={}", bedInfo.getBedId(), bedInfo.getRoomId(), bedInfo.getBedNumber());
                // 更新床位状态和老人信息
                bedInfo.setBedStatus("已占用");
                bedInfo.setElderId(contract.getElderId());
                bedInfo.setElderName(contract.getElderName());

                // 直接更新数据库
                int result = bedInfoMapper.updateById(bedInfo);
                if (result > 0) {
                    log.info("床位状态更新成功: bedId={}, status={}", bedInfo.getBedId(), bedInfo.getBedStatus());
                } else {
                    log.error("床位状态更新失败: bedId={}", bedInfo.getBedId());
                }
            } else {
                log.warn("未找到对应床位: roomId={}, bedNo={}", contract.getRoomId(), contract.getBedNumber());
            }
        } catch (Exception e) {
            log.error("更新床位状态失败", e);
        }
    }

    /**
     * 更新房间可用床位数
     *
     * @param roomId 房间ID
     */
    private void updateRoomAvailableBeds(Long roomId) {
        try {
            if (roomId == null) {
                log.warn("房间ID为空，无法更新房间可用床位数");
                return;
            }

            RoomInfo roomInfo = roomInfoMapper.selectById(roomId);
            if (roomInfo != null) {
                LambdaQueryWrapper<BedInfo> queryWrapper = Wrappers.lambdaQuery();
                queryWrapper.eq(BedInfo::getRoomId, roomId);
                queryWrapper.eq(BedInfo::getBedStatus, "空闲");
                Long availableBeds = bedInfoMapper.selectCount(queryWrapper);

                roomInfo.setAvailableBeds(availableBeds);

                if (roomInfo.getBedCount() != null && availableBeds < roomInfo.getBedCount()) {
                    roomInfo.setRoomStatus("部分可用");
                } else {
                    roomInfo.setRoomStatus("可用");
                }

                roomInfoMapper.updateById(roomInfo);
                log.info("房间可用床位数更新成功: roomId={}, availableBeds={}, status={}",
                    roomInfo.getRoomId(), roomInfo.getAvailableBeds(), roomInfo.getRoomStatus());
            } else {
                log.warn("未找到对应房间: roomId={}", roomId);
            }
        } catch (Exception e) {
            log.error("更新房间可用床位数失败", e);
        }
    }

    /**
     * 更新老人基础信息中的房间信息
     *
     * @param contract 入住合同
     */
    private void updateElderRoomInfo(AdmissionContract contract) {
        try {
            if (contract.getElderId() == null || contract.getRoomId() == null) {
                log.warn("老人ID或房间ID为空，无法更新老人房间信息");
                return;
            }

            // 获取老人基础信息
            ElderBasic elderBasic = elderBasicMapper.selectById(contract.getElderId());
            if (elderBasic == null) {
                log.warn("未找到对应老人信息: elderId={}", contract.getElderId());
                return;
            }

            // 设置老人所属房间ID
            elderBasic.setRoomId(contract.getRoomId());

            // 获取房间信息，构建完整的房间号+床位号格式
            RoomInfo roomInfo = roomInfoMapper.selectById(contract.getRoomId());
            if (roomInfo == null) {
                log.warn("未找到对应房间信息: roomId={}", contract.getRoomId());
                // 如果找不到房间，使用合同上的房间号
                String roomBedNumber = contract.getRoomNumber();
                if (StringUtils.isNotBlank(contract.getBedNumber())) {
                    // 确保床位号格式正确
                    if (contract.getBedNumber().contains("-")) {
                        roomBedNumber = contract.getBedNumber(); // 已经是完整格式
                    } else {
                        roomBedNumber = roomBedNumber + "-" + contract.getBedNumber();
                    }
                }
                elderBasic.setRoomNumber(roomBedNumber);
                log.info("使用合同信息设置老人房间号: {}", roomBedNumber);
            } else {
                // 构建房间号+床位号格式
                String roomNumber = roomInfo.getRoomNumber();
                String bedNumber = contract.getBedNumber();

                // 确保床位号格式正确
                String roomBedNumber;
                if (bedNumber.contains(roomNumber + "-")) {
                    // 如果床位号已经包含了房间号前缀，直接使用
                    roomBedNumber = bedNumber;
                    log.info("使用完整床位号: {}", roomBedNumber);
                } else if (bedNumber.contains("-")) {
                    // 如果床位号包含连字符但不是完整格式，使用房间号+床位号
                    roomBedNumber = roomNumber + "-" + bedNumber.split("-")[1];
                    log.info("构建完整床位号: {}", roomBedNumber);
                } else {
                    // 如果床位号不包含连字符，添加房间号前缀
                    roomBedNumber = roomNumber + "-" + bedNumber;
                    log.info("添加房间号前缀: {}", roomBedNumber);
                }

                // 记录日志
                log.info("设置老人房间床位号: {}", roomBedNumber);
                elderBasic.setRoomNumber(roomBedNumber);
                log.info("设置老人房间号为: {}", roomBedNumber);
            }

            // 更新老人信息
            int result = elderBasicMapper.updateById(elderBasic);
            if (result > 0) {
                log.info("老人房间信息更新成功: elderId={}, roomNumber={}", elderBasic.getElderId(), elderBasic.getRoomNumber());
            } else {
                log.error("老人房间信息更新失败: elderId={}", elderBasic.getElderId());
            }
        } catch (Exception e) {
            log.error("更新老人房间信息失败", e);
        }
    }

    /**
     * 修改入住流程
     *
     * @param bo 入住流程
     * @return 是否修改成功
     */
    @Override
    public Boolean updateByBo(AdmissionContractBo bo) {
        AdmissionContract update = MapstructUtils.convert(bo, AdmissionContract.class);
        validEntityBeforeSave(update);
        return baseMapper.updateById(update) > 0;
    }

    /**
     * 保存前的数据校验
     * 注意：已移除数据校验和特殊条款自动填充，提高系统可用性
     */
    private void validEntityBeforeSave(AdmissionContract entity){
        // 不再自动填充特殊条款，由用户自行输入
    }

    /**
     * 校验并批量删除入住流程信息
     *
     * @param ids     待删除的主键集合
     * @param isValid 是否进行有效性校验
     * @return 是否删除成功
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if(isValid){
            //TODO: Add business validation before deletion, e.g., cannot delete active/approved contracts.
            // For approved contracts, need to release bed, update room availability etc.
        }
        return baseMapper.deleteByIds(ids) > 0;
    }

    /**
     * 更新老人状态为"在院"
     *
     * @param contract 入住合同
     */
    private void updateElderActiveStatus(AdmissionContract contract) {
        try {
            if (contract.getElderId() == null) {
                log.warn("老人ID为空，无法更新老人状态");
                return;
            }

            // 获取老人基础信息
            ElderBasic elderBasic = elderBasicMapper.selectById(contract.getElderId());
            if (elderBasic == null) {
                log.warn("未找到对应老人信息: elderId={}", contract.getElderId());
                return;
            }

            // 设置老人状态为"在院"(1)
            elderBasic.setIsActive(1L);

            // 设置入住日期
            if (elderBasic.getAdmissionDate() == null && contract.getStartDate() != null) {
                elderBasic.setAdmissionDate(contract.getStartDate());
                log.info("设置老人入住日期: {}", contract.getStartDate());
            }

            // 更新老人信息
            int result = elderBasicMapper.updateById(elderBasic);
            if (result > 0) {
                log.info("老人状态更新成功: elderId={}, isActive={}, admissionDate={}",
                    elderBasic.getElderId(), elderBasic.getIsActive(), elderBasic.getAdmissionDate());
            } else {
                log.error("老人状态更新失败: elderId={}", elderBasic.getElderId());
            }
        } catch (Exception e) {
            log.error("更新老人状态失败", e);
        }
    }

    /**
     * 审核入住合同
     * @param contractId 合同ID
     * @param reviewStatus 审核状态(0:待审核 1:通过 2:退回)
     * @return 是否审核成功
     */
    @Override
    public Boolean reviewContract(Long contractId, String reviewStatus) {
        try {
            if (contractId == null || StringUtils.isEmpty(reviewStatus)) {
                log.error("审核参数不完整: contractId={}, reviewStatus={}", contractId, reviewStatus);
                return false;
            }

            // 查询合同信息
            AdmissionContract contract = baseMapper.selectById(contractId);
            if (contract == null) {
                log.error("未找到对应合同: contractId={}", contractId);
                return false;
            }

            // 更新审核状态
            contract.setIsCheckContract(reviewStatus);

            // 添加审核人和审核时间信息
            // 使用ruoyi-vue-plus框架提供的方法获取当前登录用户名
            String reviewerName = org.dromara.common.satoken.utils.LoginHelper.getUsername();
            if (StringUtils.isNotEmpty(reviewerName)) {
                log.info("设置审核人: {}", reviewerName);

                // 如果合同实体类中有reviewedBy字段，则设置审核人
                if (contract.getClass().getDeclaredFields() != null) {
                    for (java.lang.reflect.Field field : contract.getClass().getDeclaredFields()) {
                        if ("reviewedBy".equals(field.getName())) {
                            try {
                                field.setAccessible(true);
                                field.set(contract, reviewerName);
                                log.info("成功设置审核人字段: {}", reviewerName);
                            } catch (Exception e) {
                                log.warn("设置审核人字段失败: {}", e.getMessage());
                            }
                            break;
                        }
                    }
                }

                // 设置审核时间
                if (contract.getClass().getDeclaredFields() != null) {
                    for (java.lang.reflect.Field field : contract.getClass().getDeclaredFields()) {
                        if ("reviewTime".equals(field.getName())) {
                            try {
                                field.setAccessible(true);
                                field.set(contract, new java.util.Date());
                                log.info("成功设置审核时间字段");
                            } catch (Exception e) {
                                log.warn("设置审核时间字段失败: {}", e.getMessage());
                            }
                            break;
                        }
                    }
                }
            }

            boolean result = baseMapper.updateById(contract) > 0;

            if (result) {
                log.info("合同审核状态更新成功: contractId={}, newReviewStatus={}", contractId, reviewStatus);

                // 如果审核通过，分配资源
                if ("1".equals(reviewStatus)) {
                    try {
                        // 再次获取完整的合同信息，避免数据不全
                        AdmissionContract freshContract = baseMapper.selectById(contractId);
                        if (freshContract != null) {
                            // 更新资源信息
                            log.info("开始为合同分配资源: contractId={}, roomId={}, bedNumber={}, elderId={}",
                                freshContract.getContractId(), freshContract.getRoomId(),
                                freshContract.getBedNumber(), freshContract.getElderId());

                            // 0. 检查床位是否已被占用
                            checkBedAvailability(freshContract);

                            // 1. 更新床位状态
                            updateBedStatus(freshContract);

                            // 2. 更新房间可用床位数
                            updateRoomAvailableBeds(freshContract.getRoomId());

                            // 3. 更新老人房间信息
                            updateElderRoomInfo(freshContract);

                            // 4. 更新老人状态为"在院"
                            updateElderActiveStatus(freshContract);

                            // 5. 创建费用记录 - 住宿费
                            if (freshContract.getMonthlyFee() != null && freshContract.getMonthlyFee() > 0) {
                                createFeeRecord(freshContract, "住宿费", freshContract.getMonthlyFee(), "入住费用");
                                createOutstandingFee(freshContract, "住宿费", freshContract.getMonthlyFee(), "入住月费", 30);
                            }

                            // 6. 创建费用记录 - 押金
                            if (freshContract.getDeposit() != null && freshContract.getDeposit() > 0) {
                                createFeeRecord(freshContract, "押金", freshContract.getDeposit(), "入住押金");
                                createOutstandingFee(freshContract, "押金", freshContract.getDeposit(), "入住押金", 7);
                            }

                            log.info("资源分配完成: contractId={}", contractId);
                        } else {
                            log.error("审核通过但无法重新获取合同进行资源分配: contractId={}", contractId);
                        }
                    } catch (Exception e) {
                        log.error("合同审核通过后资源分配失败", e);
                        // 资源分配失败不影响审核结果
                    }
                } else if ("2".equals(reviewStatus)) {
                    log.info("合同已被退回: contractId={}", contractId);
                }
            } else {
                log.error("合同审核状态更新失败: contractId={}", contractId);
            }

            return result;
        } catch (Exception e) {
            log.error("合同审核操作失败", e);
            return false;
        }
    }

    /**
     * 创建费用记录
     *
     * @param contract 入住合同
     * @param feeType 费用类型
     * @param amount 金额
     * @param remarkPrefix 备注前缀
     */
    private void createFeeRecord(AdmissionContract contract, String feeType, Long amount, String remarkPrefix) {
        try {
            if (contract.getElderId() == null || amount == null || amount <= 0) {
                log.warn("创建费用记录参数不完整: elderId={}, amount={}", contract.getElderId(), amount);
                return;
            }

            FeeRecord feeRecord = new FeeRecord();
            feeRecord.setElderId(contract.getElderId());
            feeRecord.setElderName(contract.getElderName());
            feeRecord.setFeeType(feeType);
            feeRecord.setAmount(amount);

            // 设置当前日期时间
            feeRecord.setFeeDate(new java.util.Date());
            feeRecord.setPaymentStatus("未支付");
            feeRecord.setPaymentMethod(contract.getPaymentMethod());
            feeRecord.setRemarks(remarkPrefix + " - " + contract.getContractNo());

            int result = feeRecordMapper.insert(feeRecord);
            if (result > 0) {
                log.info("费用记录创建成功: elderId={}, feeType={}, amount={}",
                    contract.getElderId(), feeType, amount);
            } else {
                log.error("费用记录创建失败: elderId={}, feeType={}", contract.getElderId(), feeType);
            }
        } catch (Exception e) {
            log.error("创建费用记录失败", e);
        }
    }

    /**
     * 检查床位是否可用
     *
     * @param contract 入住合同
     * @throws RuntimeException 如果床位已被占用
     */
    private void checkBedAvailability(AdmissionContract contract) {
        try {
            if (contract.getRoomId() == null || StringUtils.isEmpty(contract.getBedNumber())) {
                log.warn("床位信息不完整，无法检查床位可用性: roomId={}, bedNo={}", contract.getRoomId(), contract.getBedNumber());
                return;
            }

            // 查询床位信息
            LambdaQueryWrapper<BedInfo> queryWrapper = Wrappers.lambdaQuery();
            queryWrapper.eq(BedInfo::getRoomId, contract.getRoomId());
            queryWrapper.eq(BedInfo::getBedNumber, contract.getBedNumber());

            BedInfo bedInfo = bedInfoMapper.selectOne(queryWrapper);
            if (bedInfo == null) {
                log.warn("未找到对应床位: roomId={}, bedNo={}", contract.getRoomId(), contract.getBedNumber());
                throw new RuntimeException("未找到对应床位，请检查房间号和床位号");
            }

            // 检查床位状态
            if (!"空闲".equals(bedInfo.getBedStatus())) {
                // 如果床位已被占用，但是是同一个老人，则允许继续
                if (bedInfo.getElderId() != null && bedInfo.getElderId().equals(contract.getElderId())) {
                    log.info("床位已被同一老人占用，允许继续: bedId={}, elderId={}", bedInfo.getBedId(), bedInfo.getElderId());
                    return;
                }

                log.error("床位已被占用: bedId={}, status={}, elderName={}", bedInfo.getBedId(), bedInfo.getBedStatus(), bedInfo.getElderName());
                throw new RuntimeException("床位已被占用，请选择其他床位");
            }

            log.info("床位可用: bedId={}, status={}", bedInfo.getBedId(), bedInfo.getBedStatus());
        } catch (RuntimeException e) {
            // 直接抛出运行时异常，中断处理流程
            throw e;
        } catch (Exception e) {
            log.error("检查床位可用性失败", e);
            throw new RuntimeException("检查床位可用性失败: " + e.getMessage());
        }
    }



    /**
     * 创建欠费记录
     *
     * @param contract 入住合同
     * @param feeSource 费用来源
     * @param amount 金额
     * @param feeDescription 费用描述
     * @param dueDays 到期天数
     */
    private void createOutstandingFee(AdmissionContract contract, String feeSource, Long amount,
                                     String feeDescription, int dueDays) {
        try {
            if (contract.getElderId() == null || amount == null || amount <= 0L) {
                log.warn("创建欠费记录参数不完整: elderId={}, amount={}", contract.getElderId(), amount);
                return;
            }

            ElderOutstandingFees outstandingFee = new ElderOutstandingFees();
            outstandingFee.setElderId(contract.getElderId());
            outstandingFee.setElderName(contract.getElderName());
            outstandingFee.setFeeSource(feeSource);
            outstandingFee.setFeeDescription(feeDescription);

            // 设置当前日期为账单日期
            java.util.Date billDate = new java.util.Date();
            outstandingFee.setBillDate(billDate);

            // 设置到期日期
            java.util.Calendar calendar = java.util.Calendar.getInstance();
            calendar.setTime(billDate);
            calendar.add(java.util.Calendar.DAY_OF_MONTH, dueDays);
            java.util.Date dueDate = calendar.getTime();
            outstandingFee.setDueDate(dueDate);
            outstandingFee.setPaymentDeadline(dueDate);

            outstandingFee.setTotalAmount(amount);
            outstandingFee.setPaidAmount(0L);
            outstandingFee.setOutstandingAmount(amount);
            outstandingFee.setPaymentStatus("未支付");
            outstandingFee.setIsOverdue("0");
            outstandingFee.setOverdueDays(0L);
            outstandingFee.setReminderCount(0L);
            outstandingFee.setRemarks(contract.getElderName() + " - " + feeDescription + " - " + contract.getContractNo());

            int result = elderOutstandingFeesMapper.insert(outstandingFee);
            if (result > 0) {
                log.info("欠费记录创建成功: elderId={}, feeSource={}, amount={}",
                    contract.getElderId(), feeSource, amount);
            } else {
                log.error("欠费记录创建失败: elderId={}, feeSource={}", contract.getElderId(), feeSource);
            }
        } catch (Exception e) {
            log.error("创建欠费记录失败", e);
        }
    }
}
